package licode.unisop.provider.vo;

import licode.unisop.provider.utils.PluginUtil;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 属性集合信息
 *
 * @author licode
 */
public class SiProps extends HashMap<String, Object> implements Serializable {
    private static final long serialVersionUID = 659021663400282503L;
    public static final SiProps EMPTY = new SiProps();

    public SiProps copy() {
        SiProps cloneProp = new SiProps();
        cloneProp.putAll(this);
        return cloneProp;
    }

    public boolean isEmpty() {
        return super.isEmpty();
    }

    public static SiProps build(Map<String, Object> map) {
        SiProps props = new SiProps();
        map.forEach(props::addProp);
        return props;
    }

    public Map<String, Object> toMap() {
        return new HashMap<>(this);
    }

    public SiProps addProp(String name, Object obj) {
        if (null != obj) {
            this.put(name, obj);
        }
        return this;
    }

    public SiProps addItems(List<SiPropItem> items) {
        if (null != items && !items.isEmpty()) {
            items.forEach(item -> this.put(item.getName(), item.getValue()));
        }
        return this;
    }

    public SiProps addProps(SiProps props) {
        if (null != props && !props.isEmpty()) {
            this.putAll(props);
        }
        return this;
    }

    public SiProps removeProp(String name) {
        this.remove(name);
        return this;
    }

    public SiProps setItems(List<SiPropItem> items) {
        this.clear();

        if (null != items && !items.isEmpty()) {
            items.forEach(item -> this.put(item.getName(), item.getValue()));
        }

        return this;
    }

    public List<SiPropItem> getPropItems() {
        return this.entrySet().stream().map(item -> SiPropItem.builder()
                .name(item.getKey())
                .value(item.getValue())
                .build()).collect(Collectors.toList());
    }

    public boolean getBool(String name, boolean defVal) {
        Object val = this.get(name);
        if (null == val) {
            return defVal;
        } else if (val instanceof Boolean) {
            return (Boolean) val;
        } else {
            return defVal;
        }
    }

    public String getString(String name, String defVal) {
        Object val = this.get(name);
        if (null == val) {
            return defVal;
        } else if (val instanceof String) {
            return (String) val;
        } else {
            return val.toString();
        }
    }

    public LocalDate getLocalDate(String name, LocalDate defVal) {
        Object val = this.get(name);
        if (null == val) {
            return defVal;
        } else if (val instanceof LocalDate) {
            return (LocalDate) val;
        } else {
            return PluginUtil.parseDate(val.toString());
        }
    }

    public LocalDateTime getLocalDateTime(String name, LocalDateTime defVal) {
        Object val = this.get(name);
        if (null == val) {
            return defVal;
        } else if (val instanceof LocalDateTime) {
            return (LocalDateTime) val;
        } else {
            return PluginUtil.parseDateTime(val.toString());
        }
    }

    public Long getLong(String name, Long defVal) {
        Object val = this.get(name);
        if (null == val) {
            return defVal;
        } else if (val instanceof Long) {
            return (Long) val;
        } else if (val instanceof Integer) {
            return ((Integer) val).longValue();
        } else if (val instanceof Short) {
            return ((Short) val).longValue();
        } else {
            try {
                return Long.parseLong(val.toString());
            } catch (NumberFormatException e) {
                return defVal;
            }
        }
    }

    public Integer getInt(String name, Integer defVal) {
        Object val = this.get(name);
        if (null == val) {
            return defVal;
        } else if (val instanceof Integer) {
            return (Integer) val;
        } else if (val instanceof Short) {
            return ((Short) val).intValue();
        } else {
            try {
                return Integer.parseInt(val.toString());
            } catch (NumberFormatException e) {
                return defVal;
            }
        }
    }

    public Double getDouble(String name, Double defVal) {
        Object val = this.get(name);
        if (null == val) {
            return defVal;
        } else if (val instanceof Double) {
            return (Double) val;
        } else if (val instanceof Float) {
            return ((Float) val).doubleValue();
        } else {
            try {
                return Double.parseDouble(val.toString());
            } catch (NumberFormatException e) {
                return defVal;
            }
        }
    }

    public Object getValue(String name) {
        return this.get(name);
    }


    public boolean contain(String name) {
        return this.containsKey(name);
    }
}
